<?php
namespace Cola;
/**
 *
 * @property View $view
 * @property Request $request
 * @property Response $response
 * @property Config $config
 *
 */
abstract class Controller
{
    public $isDebug = APP_DEBUG;

    /**
     * Constructor
     *
     */
    public function __construct()
    {
        $this->get = $_GET;
        $this->post = $_POST;
        method_exists($this, '_init') && $this->_init();
    }

    /**
     * Magic method
     *
     * @param string $method
     * @param array $args
     *
     * @throws Exception
     */
    public function __call($method, $args)
    {
        $cls = get_class($this);
        throw new Exception("Call to undefined method: {$cls}->{$method}()");
    }

    /**
     * Get var
     *
     * @param string $key
     * @param mixed  $default
     *
     * @return mixed
     */
    protected function get($key = null, $default = null)
    {
        return Request::get($key, $default);
    }

    /**
     * Post var
     *
     * @param string $key
     * @param mixed  $default
     *
     * @return mixed
     */
    protected function post($key = null, $default = null)
    {
        return Request::post($key, $default);
    }

    /**
     * 成功
     * @param $data
     * @param $code
     * @return void
     */
    protected function success($data, $code = 1)
    {
        $this->response->json($code, '', $data);
    }

    /**
     * 失败
     * @param $message
     * @param $code
     * @param $data
     * @return void
     */
    protected function error($message, $code = 0, $data = array())
    {
        $this->response->json($code, $message, $data);
    }

    protected function backError($message, $code = 0, $data = array())
    {
        $this->response->json($code, $message, $data);
    }

    /**
     * View
     *
     * @param array $file
     * @return View
     */
    protected function view($file = null)
    {
        empty($file) && $file = $this->defaultTemplate();
        return $this->view = new View($file);
    }

    /**
     * Display the view
     *
     * @param string $file
     * @param string $layout
     */
    protected function display($file = null, $layout = null)
    {
        empty($file) && $file = $this->defaultTemplate();
        $this->view->file = $file;
        $this->view->display($layout);
    }

    /**
     * Get default template file path
     *
     * @return string
     */
    protected function defaultTemplate()
    {
        $di = Cola::getInstance()->getDispatchInfo();
        $controller = strtolower(substr($di['controller'], 0, -10));
        $action = strtolower(substr($di['action'], 0, -6));
        $home = Cola::getConfig('_moduleHome');
        return "{$home}/views/{$controller}.{$action}.php";
    }

    /**
     * Redirect to other url
     *
     * @param string $url
     * @param int    $code
     */
    protected function redirect($url, $code = 302)
    {
        $this->response->redirect($url, $code);
    }

    /**
     * Abort
     *
     * @param mixed  $data
     * @param string $callback callback function name
     * @param string $encode
     */
    protected function abort($data, $callback = null, $encode = 'utf-8')
    {
        is_string($data) || $data = json_encode($data, JSON_UNESCAPED_UNICODE);

        if ($callback && (preg_match('/^[a-zA-Z\d_]+$/', $callback))) {
            Response::charset($encode, 'application/javascript');
            echo "{$callback}({$data})";
        } else {
            Response::charset($encode, 'application/json');
            echo $data;
        }

        exit();
    }

    /**
     * Dynamic set vars
     *
     * @param string $key
     * @param mixed $value
     */
    public function __set($key, $value = null)
    {
        $this->$key = $value;
    }

    /**
     * Dynamic get vars
     *
     * @param string $key
     *
     * @return \Cola\Config|\Cola\Request|\Cola\Response|\Cola\View
     * @throws \Cola\Exception
     */
    public function __get($key)
    {
        switch ($key) {
            case 'view':
                return $this->view();

            case 'request':
                $this->request = new Request();
                return $this->request;

            case 'response':
                $this->response = new Response();
                return $this->response;

            case 'config':
                $this->config = Cola::getInstance()->config();
                return $this->config;

            default:
                throw new Exception('Undefined property: ' . get_class($this) . '::' . $key);
        }
    }
    
    /**
     * 实例化模型
     * @param string $name
     * @return \Cola\Model
     */
    protected function model($name = null)
    {
        /* @var \Cola\Model $model */
        $model = Cola::model($name);
        $model->isDebug = $this->isDebug;
        return $model;
    }

    /**
     * 给模板（视图）变量赋值
     * @param array|string $key 变量名或者整个变量数组
     * @param string       $value 值
     *
     * @return Controller
     */
    public function assign($key, $value = '')
    {
    	$this->view->assign($key, $value);
    	return $this;
    }
}
